Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

solana: timelock preloading ops authority #474

Merged
merged 34 commits into from
Jan 28, 2025

Conversation

jadepark-dev
Copy link
Contributor

@jadepark-dev jadepark-dev commented Jan 19, 2025

This PR enhances operation authority management and separates proposer/bypasser operation paths

Primary Changes

  • Separated operation PDAs for proposer and bypasser roles using distinct seeds
  • Added strict role access validation for operation management (initialize/append/finalize/+clear)
  • Enhanced access control to support multiple role authorization
  • Restructured instruction account validation for role-based access
  • Implemented automatic PDA closure after bypasser operation execution

Others

  • Modified instruction account structures to include role access controller
  • Updated test suites to validate role-based access patterns
  • Improved error handling for unauthorized operation attempts
  • Enhanced test coverage for operation preloading and execution flows

@jadepark-dev jadepark-dev changed the title Solana/timelock preload op auth solana: proposer role as timelock preloading ops authority Jan 19, 2025
@jadepark-dev jadepark-dev self-assigned this Jan 20, 2025
@jadepark-dev jadepark-dev marked this pull request as ready for review January 20, 2025 05:25
@jadepark-dev jadepark-dev requested a review from a team as a code owner January 20, 2025 05:25
@jadepark-dev jadepark-dev marked this pull request as draft January 21, 2025 05:07
@jadepark-dev jadepark-dev changed the title solana: proposer role as timelock preloading ops authority solana: timelock preloading ops authority Jan 21, 2025
@jadepark-dev jadepark-dev marked this pull request as ready for review January 23, 2025 07:52
@@ -171,6 +172,8 @@ func (value TimelockError) String() string {
return "OperationNotCancellable"
case OperationNotReady_TimelockError:
return "OperationNotReady"
case OperationAlreadyExecuted_TimelockError:
return "OperationAlreadyExecuted"
Copy link
Contributor Author

@jadepark-dev jadepark-dev Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: on attempt on bypasser execute already executed operation

err = common.GetAccountDataBorshInto(ctx, solanaGoClient, opToSchedule.OperationPDA(), config.DefaultCommitment, &opAccount)
if err != nil {
require.NoError(t, err, "failed to get account info")
if bytes.Equal(op.Data[:8], timelock.Instruction_ScheduleBatch[:]) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: filtering schedule_batch instruction only to verify event emission, since preload ixs are in mcm operations together

pub struct BypasserExecuteBatch<'info> {
#[account(
mut,
seeds = [TIMELOCK_OPERATION_SEED, timelock_id.as_ref(), id.as_ref()],
bump,
constraint = operation.is_finalized @ TimelockError::OperationNotFinalized,
constraint = !operation.is_done() @ TimelockError::OperationAlreadyExecuted,
close = authority, // close the operation after execution
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: bypasser_execution operation management, the operation is needed to be pre-uploaded, but it shouldn't affect normal schedule/execute workflow so we're closing the account

@@ -23,44 +23,46 @@ pub enum TimelockError {
#[msg("Provided ID is invalid")]
InvalidId,

#[msg("RBACTimelock: operation not finalized")]
#[msg("operation not finalized")]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: clean up error messages but subject to change on the off-chain requirement

@@ -78,8 +80,6 @@ pub fn execute_batch<'info>(
});
}

require!(op.is_ready(current_time), TimelockError::OperationNotReady);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: In the EVM-based version, we do a second is_ready check after executing all calls to guard against reentrancy mid-transaction, which might invalidate the operation. On Solana, however, each instruction is atomic and there is no reentrancy model that would allow an external actor to modify our operation state during its execution. Therefore, the second check is unnecessary here.

aalu1418
aalu1418 previously approved these changes Jan 23, 2025
@jadepark-dev jadepark-dev requested a review from aalu1418 January 24, 2025 10:37
/// Implementation uses separate code paths and PDAs for each operation type
/// to maintain clear security boundaries and audit trails, despite similar logic.
/// All operations enforce state transitions, size limits, and role-based access.
///
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: while it is technically possible to reduce the number of lines between normal / bypasser operation management instructions by employing dynamic seeds or Anchor macro in this file, having analyzed the implementation, I found that it rendered the interface overly complex and substantially reduced readability.

@jadepark-dev jadepark-dev requested a review from a team January 24, 2025 11:14
@jadepark-dev jadepark-dev mentioned this pull request Jan 24, 2025
3 tasks
Copy link

Metric solana/timelock-preload-op-auth main
Coverage 76.4% 76.3%

@jadepark-dev jadepark-dev merged commit 9b02e50 into main Jan 28, 2025
17 checks passed
graham-chainlink added a commit to smartcontractkit/mcms that referenced this pull request Jan 29, 2025
- Address [latest breaking change](smartcontractkit/chainlink-ccip#474) from the solana program to incorporate new bypasser seed
- updated e2e

JIRA: https://smartcontract-it.atlassian.net/browse/DPA-1494
graham-chainlink added a commit to smartcontractkit/mcms that referenced this pull request Jan 29, 2025
- Address [latest breaking change](smartcontractkit/chainlink-ccip#474) from the solana program to incorporate new bypasser seed
- updated e2e

JIRA: https://smartcontract-it.atlassian.net/browse/DPA-1494
graham-chainlink added a commit to smartcontractkit/mcms that referenced this pull request Jan 29, 2025
- Address [latest breaking change](smartcontractkit/chainlink-ccip#474) from the solana program to incorporate new bypasser seed
- updated e2e

JIRA: https://smartcontract-it.atlassian.net/browse/DPA-1494
github-merge-queue bot pushed a commit to smartcontractkit/mcms that referenced this pull request Jan 29, 2025
…s latest breaking change (#271)

Dependent on [this
PR](#270) updating the rest
of the [API breaking
change](smartcontractkit/chainlink-ccip#474).

- Uses the new seed `timelock_bypasser_operation` for bypass operation
for timelock converter.
- Preload instructions for timelock bypasser from initialise to finalize
- Updated e2e

JIRA: https://smartcontract-it.atlassian.net/browse/DPA-1494
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants